package gameManager;

/**
 * Klasa zarządcy stołów, odpowiedzialna za zakładanie, usuwanie stołów w różnych przypadkach
 * wejścia do gry, utworzenia gry, wyjścia przedwczesnego i wszystkich innych.
 * Pośredniczy też pomiędzy CommandExecutrem a GameManagerem w przypadku konieczności
 * wykonania komendy od serwera - odnajduje stół na którym ma być komenda wykonana.
 * @author Konrad Sobczak
 * @author Kamil Nowak
 */
import java.util.concurrent.*;
import zarzadcyZdarzen.*;
import bierki.*;

public class TableManager {

	/**
	 * referencja na EventDispacher - potrzeba wykonać jego metody w przypadku założenia lub zamknięcia stołu
	 */
	private EventDispacher ed;
	private ConcurrentHashMap<Integer,GameManager> stoly;
	
	public void setEventDispacher(EventDispacher ed){
		this.ed = ed;
	}
	 
	public TableManager(){
		stoly = new ConcurrentHashMap<Integer,GameManager>();
		
	}

	/**
	 * Znajduje stół po id, wywołuje jego metodę aktualizuj_szachownicę w celu wykonania na ekranie
	 * i w stanie gry ruchu którego dokonał przeciwnik
	 * @param id_stolu - id stołu na którym ma zostać wykonany ruch
	 * @param xp - początkowa pozycja x z której jest wykonywany ruch 
	 * @param yp - początkowe y
	 * @param xk - końcowe x
	 * @param yk - końcowe y
	 */
	public void dokonaj_ruchu(int id_stolu, int xp, int yp, int xk, int yk){
		stoly.get(new Integer(id_stolu)).aktualizuj_szachownice(xp,yp,xk,yk);
	}
	
	/**
	 * W przypadku gdy przeciwnik dokona pronmocji swojego pionka zamiast komendy
	 * MOVE przychodzi PROMO, więc należy wykonać ruch przeciwnika,a następnie dokonać
	 * promocji także po naszej stronie
	 * 
	 * @param id_stolu - id stołu na którym ma zostąć dokonana promocja
	 * @param xp - pozycja początkowa x promowanego pionka 
	 * @param yp - pozycja początkowa y promowanego pionka
	 * @param xk - pozycja końcowa x promowanego pionka
	 * @param yk - pozycja końcowa y promowanego pionka
	 * @param symbol - symbol figury na którą pionek ma być promowany
	 */
	public void dokonaj_promo(int id_stolu, int xp, int yp, int xk, int yk,int symbol){
		stoly.get(new Integer(id_stolu)).aktualizuj_szachownice(xp,yp,xk,yk);
		stoly.get(new Integer(id_stolu)).wypromuj(xk,yk,symbol);
		
	}
	
	/**
	 * Koniec gry na danym stole, w przypadku komunikatu ENDGAME dla stołu
	 * o podanym id_stolu następuje koniec gry z komunikatem zależnym od kodu jaki
	 * przyjdzie z komendą. Jeśli dokonał się już jakiś ruch to rozłączający się przegrywa,
	 * w przeciwnym razie partia pozostaje nierozstrzygnięta.
	 * @param id_stolu - id stołu na którym następuje koniec gry
	 * @param kod - koc z jakim następuje zakończenie stołu - od niego zależne są
	 * komunikaty pokazywane użytkownikowi
	 */
	public void koniec_gry(int id_stolu,int kod){
		if(kod==2){
			if(stoly.containsKey(new Integer(id_stolu))){
				stoly.get(new Integer(id_stolu)).koniec_gry("przeciwnik rozłączył się, WYGRAŁEŚ!!!");
				stoly.get(new Integer(id_stolu)).zamknij_z_zewnatrz();
				if(stoly.get(new Integer(id_stolu)).get_czy_czarny())
					this.zamknij_stol(id_stolu);
				else
					this.zamknij_stol_bez_leave(id_stolu);
			}
		}
		if(kod==1){
			if(stoly.containsKey(new Integer(id_stolu))){
			stoly.get(new Integer(id_stolu)).koniec_gry("przeciwnik rozłączył się, nie wykonano ruchu \n partia NIEROZSTRZYGNIĘTA");
				stoly.get(new Integer(id_stolu)).zamknij_z_zewnatrz();
				if(stoly.get(new Integer(id_stolu)).get_czy_czarny())
					this.zamknij_stol(id_stolu);
				else
					this.zamknij_stol_bez_leave(id_stolu);
			}
		}
	}
	
	
	/**
	 * Koniec gry w przypadku dania mata
	 * @param id_stolu - id stołu na którym nastąpiło to zdarzenie
	 */
	public void finish_game(int id_stolu){
			if(stoly.containsKey(new Integer(id_stolu))){
				stoly.get(new Integer(id_stolu)).zamknij_z_zewnatrz();
				if(stoly.get(new Integer(id_stolu)).get_czy_czarny())
					this.zamknij_stol(id_stolu);
				else
					this.zamknij_stol_bez_leave(id_stolu);
			}
		
	}
	
	/**
	 * Dodaj do odpowiedniego stołu komunikat chat
	 * @param id_stolu - na jakim stole dodać komunikat
	 * @param kto - kto wysłał komunikat
	 * @param co - co powiedział
	 */
	public  void dodajChatMsg(int id_stolu, String kto, String co){
		stoly.get(new Integer(id_stolu)).dodajChatMsg(kto,co);
	}
	
	/**
	 * Rozpoczęcie gry po wejściu do niej przeciwnika
	 * @param id_stolu - id stołu na którym nastąpiło dołączenie do gry
	 * @param imie_przeciwnika - imię przeciwnika dołączającego
	 */
	public void rozpocznij_gre(int id_stolu,String imie_przeciwnika){
		if(stoly.containsKey(new Integer(id_stolu)))
			stoly.get(new Integer(id_stolu)).rozpocznij_gre(imie_przeciwnika);
	}
	
	
	/**
	 * Kiedy serwer zwróci komende o prawidłowym założeniu stołu należy jeszcze dokonać
	 * tego po stronie klienta - następuje to w tej metodzie
	 * @param id_stol - zwrócony przez serwer przynależny naszemu stołowi id
	 * @param stan_poczatkowy - stan początkowy, true/false oznacza grę białymi lub czarnymi.
	 */
	public void zaloz_stol(int id_stol,boolean stan_poczatkowy){
		stoly.put(new Integer(id_stol),new GameManager(this,ed,id_stol,stan_poczatkowy));
		//System.out.println("To jest id stolu: " + id_stol);
	}
	
	/**
	 * Kiedy użytkownik zdecyduje się na założenie stołu wysyłana jest odpowiednia komenda do serwer
	 * @param id_user - id użytkownika który stół zakłada
	 * @param login - login użytkownika który stół zakłada
	 * @param tableName - nazwa zakładanego stołu
	 */
	public void new_table(long id_user,String login,String tableName){
		ed.sendCreateTable(id_user,login,tableName);
	}
	
	/**
	 * Zamyka stół
	 * @param id_stolu - id stołu do zamknięcia
	 */
	public void zamknij_stol_bez_leave(int id_stolu){
		if(stoly.containsKey(new Integer(id_stolu)))
			stoly.remove(new Integer(id_stolu));
	}
	
	/**
	 * Zamyka stół i wysyła komunikat o jego opuszczeniu
	 * @param id_stolu - id stołu do zamknięcia
	 */
	public  void zamknij_stol(int id_stolu){
		ed.sendLeaveTable(id_stolu);
		if(stoly.containsKey(new Integer(id_stolu)))
			stoly.remove(new Integer(id_stolu));
	}
	
}
